package chen.yi.component.idempotent.aspect;

import chen.yi.component.idempotent.annotate.RepeatSubmit;
import chen.yi.component.idempotent.constant.RedisKey;
import chen.yi.component.idempotent.sign.SignInterface;
import chen.yi.component.redis.utils.RedisUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 基于切面表达式防止重复提交
 * @author huat
 **/
@Aspect
public class ExpressionRepeatAspect implements MethodInterceptor {
    private final Long interval;
    private final String message;
    private final SignInterface signInterface;

    public ExpressionRepeatAspect(SignInterface signInterface, Long interval, String message) {
        this.interval = interval;
        this.message = message;
        this.signInterface = signInterface;
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        //获取切入点所在的方法
        Method method = invocation.getMethod();
        // 获取请求上下文
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //redis key
        String key = RedisKey.REPEAT_KEY + signInterface.getUserSign(request) + ":" + request.getRequestURI();
        Object o = RedisUtil.get(key);

        //判断是否为空
        //判断最后操作时间距离现在时间是否超过配置最小请求时间
        if (!Objects.isNull(o) && System.currentTimeMillis() - Long.parseLong(o.toString()) < interval) {
            HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
            PrintWriter writer =null;
            try {
                response.setContentType("application/json");
                response.setCharacterEncoding("UTF-8");
                writer = response.getWriter();
                writer.write("{\"code\":500,\"message\":\""+message+"\"}");
                writer.flush();
            }finally {
                if (Objects.nonNull(writer)) {
                    writer.close();
                }
            }
            return null;
        }
        RedisUtil.set(key, System.currentTimeMillis(), interval, TimeUnit.MILLISECONDS);
        return invocation.proceed();
    }

}
